package com.dhl.fin.api.controller;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.dhl.fin.api.common.dto.ApiResponse;
import com.dhl.fin.api.common.service.ExceptionRecordService;
import com.dhl.fin.api.common.service.RedisService;
import com.dhl.fin.api.common.util.JsonUtil;
import com.dhl.fin.api.common.util.MapUtil;
import com.dhl.fin.api.common.util.ObjectUtil;
import com.dhl.fin.api.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.transaction.Transactional;
import java.util.Map;

/**
 * @author CuiJianbo
 * @since 2025/3/16
 */
@Slf4j
@RestController
@RequestMapping("wechat")
@Transactional
public class WeChatController {

    @Value("${wechat.miniProgram.loginUrl}")
    private String loginUrl;

    @Value("${wechat.miniProgram.tokenUrl}")
    private String tokenUrl;

    @Value("${wechat.miniProgram.subscribe.notifyUrl}")
    private String miniProgramSubscribeSendUrl;

    @Value("${wechat.service.subscribe.notifyUrl}")
    private String subscribeUrl;

    @Value("${wechat.service.template.sendUrl}")
    private String templateSendUrl;


    @Value("${wechat.service.template.remindTemplateId}")
    private String remindTemplateId;

    @Autowired
    private RedisService redisService;

    @Autowired
    private ExceptionRecordService exceptionRecordService;

    /**
     * 登录微信
     */
    @ResponseBody
    @PostMapping("login")
    public ApiResponse login(@RequestBody WeChatLoginReqDTO loginDto) {
        String finalUrl = String.format("%s?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", loginUrl, loginDto.getAppId(), loginDto.getSecret(), loginDto.getCode());
        String jsonData = HttpRequest.get(finalUrl).execute().body();
        Map responseData = JsonUtil.parseToMap(jsonData);

        if (responseData.containsKey("openid")) {
            String openId = MapUtil.getString(responseData, "openid");
            String sessionKey = MapUtil.getString(responseData, "session_key");
            log.info("在微信服务器上登录成功返回数据-> {}", jsonData);
            return ApiResponse.success(MapUtil.builder()
                    .add("openId", openId)
                    .add("sessionKey", sessionKey)
                    .build());
        } else {
            log.error("登录微信服务器失败-> {}", jsonData);
            exceptionRecordService.addRecordLog("20000", "登录微信服务器失败", "返回的数据是：" + jsonData);
            return ApiResponse.error("登录微信服务器失败");
        }

    }

    /**
     * 获取token
     */
    @ResponseBody
    @GetMapping("getToken")
    public ApiResponse getToken(WeChatTokenRequestDTO requestDTO) {
        WeChatTokenReqDTO weChatTokenReqDTO = new WeChatTokenReqDTO();
        ObjectUtil.copyFieldValue(requestDTO, weChatTokenReqDTO);
        weChatTokenReqDTO.setGrant_type("client_credential");
        String token = redisService.getString("wechat:token:" + requestDTO.getAppid());

        if (ObjectUtil.isNull(token)) {
            try {
                String respJsonData = HttpUtil.get(tokenUrl, MapUtil.beanToMap(weChatTokenReqDTO));
                Map data = JsonUtil.parseToMap(respJsonData);
                if (data.containsKey("errcode")) {
                    String msg = data.get("errmsg").toString();
                    log.error("获取token失败，{}", msg);
                    exceptionRecordService.addRecordLog("20001", "获取token失败", "返回的数据是：" + respJsonData);
                    return ApiResponse.error(msg);
                }
                log.info("成功发送消息");
                token = MapUtil.getString(data, "access_token");
                redisService.putString("wechat:token:" + requestDTO.getAppid(), token, 1);
            } catch (Exception e) {
                log.error("获取token失败:{}", e.getMessage(), e);
                exceptionRecordService.addRecordLog("20001", "获取token失败", e.getMessage());
                return ApiResponse.error("获取token失败");
            }
        }

        return ApiResponse.success(token);

    }

    /**
     * 小程序给用户发送订阅消息
     */
    @ResponseBody
    @PostMapping("miniProgramSendMsg")
    public ApiResponse miniProgramSendMessage(@RequestBody WeChatMiniProgramMessageReqDTO messageBodyReqDTO) {
        String respJsonData;

        String postUrl = String.format("%s?access_token=%s", miniProgramSubscribeSendUrl, messageBodyReqDTO.getAccess_token());
        try {
            respJsonData = HttpUtil.post(postUrl, JsonUtil.objectToString(messageBodyReqDTO.convertToBodyReqDTO()));
        } catch (Exception e) {
            log.error("发送通知消息失败:{}", e.getMessage(), e);
            exceptionRecordService.addRecordLog("20002", "小程序给用户发送通知消息失败", e.getMessage());
            return ApiResponse.error("发送通知消息失败");
        }
        Map data = JsonUtil.parseToMap(respJsonData);
        if (data.containsKey("errcode") && MapUtil.getInteger(data, "errcode") != 0) {
            String msg = data.get("errmsg").toString();
            log.error("发送通知消息失败，{}", msg);
            exceptionRecordService.addRecordLog("20002", "小程序给用户发送通知消息失败", "返回的数据是：" + respJsonData);
            return ApiResponse.error(msg);
        }
        return ApiResponse.success();
    }

    /**
     * 服务号给用户发送订阅消息
     */
    @ResponseBody
    @PostMapping("sendMsg")
    public ApiResponse sendWeChatMessage(@RequestBody WeChatMessageReqDTO messageBodyReqDTO) throws Exception {
        String respJsonData;

        String postUrl = String.format("%s?access_token=%s", subscribeUrl, messageBodyReqDTO.getAccess_token());
        try {
            respJsonData = HttpUtil.post(postUrl, JsonUtil.objectToString(messageBodyReqDTO.convertToBodyReqDTO()));
        } catch (Exception e) {
            log.error("发送通知消息失败:{}", e.getMessage(), e);
            exceptionRecordService.addRecordLog("20003", "服务号给用户发送通知消息失败", e.getMessage());
            return ApiResponse.error("发送通知消息失败");
        }
        Map data = JsonUtil.parseToMap(respJsonData);
        if (data.containsKey("errcode") && MapUtil.getInteger(data, "errcode") != 0) {
            String msg = data.get("errmsg").toString();
            log.error("发送通知消息失败，{}", msg);
            exceptionRecordService.addRecordLog("20003", "服务号给用户发送通知消息失败", "返回的数据是：" + respJsonData);
            return ApiResponse.error(msg);
        }
        return ApiResponse.success();
    }


    /**
     * 发送模版消息
     */
    @ResponseBody
    @PostMapping("templateMsg")
    public ApiResponse sendTemplateMsg(@RequestBody WeChatMessageReqDTO messageBodyReqDTO) throws Exception {
        String respJsonData;

        String postUrl = String.format("%s?access_token=%s", templateSendUrl, messageBodyReqDTO.getAccess_token());
        try {
            respJsonData = HttpUtil.post(postUrl, JsonUtil.objectToString(messageBodyReqDTO.convertToBodyReqDTO()));
        } catch (Exception e) {
            log.error("发送通知消息失败:{}", e.getMessage(), e);
            exceptionRecordService.addRecordLog("20004", "发送模版消息失败",  e.getMessage());
            return ApiResponse.error("发送通知消息失败");
        }
        Map data = JsonUtil.parseToMap(respJsonData);
        if (data.containsKey("errcode") && MapUtil.getInteger(data, "errcode") != 0) {
            String msg = data.get("errmsg").toString();
            log.error("发送通知消息失败，{}", msg);
            exceptionRecordService.addRecordLog("20004", "发送模版消息失败", "返回的数据是：" + respJsonData);
            return ApiResponse.error(msg);
        }
        return ApiResponse.success();
    }


//    /**
//     * 发送待办记的提醒通知消息
//     */
//    @ResponseBody
//    @PostMapping("remind/templateMsg")
//    public ApiResponse remindTemplateSendUrl(@RequestBody WeChatMessageReqDTO messageBodyReqDTO) throws Exception {
//        messageBodyReqDTO.setTemplate_id(remindTemplateId);
//        String respJsonData;
//        String postUrl = String.format("%s?access_token=%s", templateSendUrl, messageBodyReqDTO.getAccess_token());
//        try {
//            respJsonData = HttpUtil.post(postUrl, JsonUtil.objectToString(messageBodyReqDTO.convertToBodyReqDTO()));
//        } catch (Exception e) {
//            log.error("发送通知消息失败:{}", e.getMessage(), e);
//            return ApiResponse.error("发送通知消息失败");
//        }
//        Map data = JsonUtil.parseToMap(respJsonData);
//        if (data.containsKey("errcode") && MapUtil.getInteger(data, "errcode") != 0) {
//            String msg = data.get("errmsg").toString();
//            log.error("发送通知消息失败，{}", msg);
//            return ApiResponse.error(msg);
//        }
//        return ApiResponse.success();
//    }


}
